// sm4-util.js
const sm4 = require('sm-crypto').sm4;
const crypto = require('crypto');

class SM4Crypto {
  /**
   * 构造函数
   * @param {string} key - 16字节的十六进制密钥（32字符）
   * @param {string} [iv] - CBC模式需要的16字节初始化向量（32字符）
   */
  constructor(key, iv = null) {
    this.key = key;
    this.iv = iv;
    this.validateKey();
  }

  // 校验密钥格式
  validateKey() {
    if (!/^[0-9a-f]{32}$/i.test(this.key)) {
      throw new Error('Invalid SM4 key: must be 32-character hex string');
    }
  }

  /**
   * 加密
   * @param {string|Buffer} plaintext - 明文
   * @param {string} [mode='ecb'] - 加密模式 (ecb/cbc)
   * @returns {string} 十六进制密文
   */
  encrypt(plaintext, mode = 'ecb') {
    const options = { mode };
    if (mode === 'cbc') {
      if (!this.iv || !/^[0-9a-f]{32}$/i.test(this.iv)) {
        throw new Error('CBC mode requires a valid 32-character hex IV');
      }
      options.iv = this.iv;
    }
    return sm4.encrypt(plaintext, this.key, options);
  }

  /**
   * 解密
   * @param {string} ciphertext - 十六进制密文
   * @param {string} [mode='ecb'] - 解密模式 (ecb/cbc)
   * @returns {string} 明文
   */
  decrypt(ciphertext, mode = 'ecb') {
    const options = { mode };
    if (mode === 'cbc') {
      if (!this.iv || !/^[0-9a-f]{32}$/i.test(this.iv)) {
        throw new Error('CBC mode requires a valid 32-character hex IV');
      }
      options.iv = this.iv;
    }
    return sm4.decrypt(ciphertext, this.key, options);
  }

  /**
   * 生成随机密钥（静态方法）
   * @returns {string} 32字符的十六进制密钥
   */
  static generateKey() {
    return crypto.randomBytes(16).toString('hex');
  }

  /**
   * 生成随机IV（静态方法）
   * @returns {string} 32字符的十六进制IV
   */
  static generateIV() {
    return crypto.randomBytes(16).toString('hex');
  }
}

module.exports = SM4Crypto;